﻿using System;
using System.Collections.Generic;

namespace TeamDraft
{
    public class TeamDraft
    {
        private DraftEvent m_draftevent = null;
        private int m_pick = 0;
        //private int m_lastpick = 0;
        private List<string> m_teams = new List<string>();
        private List<Pick> m_picks = new List<Pick>();

        /// <summary>
        /// Default Initiator
        /// </summary>
        /// <remarks>We may want to add a return to confim proper execution.  Will only create the default draft.</remarks>
        /// <returns>None</returns>
        public TeamDraft()
        {
            m_draftevent = new DraftEvent();
            Initialize();
        }

        /// <summary>
        /// Primary Initiator for creating Team Draft
        /// </summary>
        /// <remarks>We may want to add a return to confim proper execution.</remarks>
        /// <param name="draftevent">Initial draft parameters</param>
        public TeamDraft(DraftEvent draftevent)
        {
            m_draftevent = draftevent;
            Initialize();
        }

        public DraftEvent Draft
        {
            get
            {
                return m_draftevent;
            }
            set
            {
                m_draftevent = value;
            }
        }

        //#ms The following three properties do not have a set value because the are read only.
        public int LastPick
        {
            //#ms I am including this to account for times when multiple teams can draft because of expired times, 
            //#ms this would need some active update code to track the last full pick.
            //#ms for now count is good
            get
            {
                return m_picks.Count - 1;
            }
        }


        public List<string> Teams
        {
            get
            {
                return m_teams;
            }
            set
            {
                m_teams = value;
            }
        }

        public List<Pick> Picks
        {
            get
            {
                return m_picks;
            }
            set
            {
                m_picks = value;
            }
        }

        public int Pick()
        {
            return m_picks.Count + 1;  //returns current pick index
        }

        public int Pick(int pickedid)
        {
            Pick foundpickid;

            foundpickid = m_picks.Find(delegate(Pick i)
            {
                if (i.PickedID == pickedid) return true;
                else return false;
            });

            return foundpickid.PickIndex;  //returns pick index of the pickedid
        }

        public Pick Pick(int team, int round)
        {
            Pick picklookup = new Pick();

            if ((team > m_draftevent.TeamCount) || (team < 1)) return picklookup;
            if ((round > m_draftevent.RoundCount) || (team < 1)) return picklookup;

            int pickindex;

            switch (m_draftevent.Style)
            {
                case DraftStyle.Regular:
                    team = team - 1;
                    break;
                case DraftStyle.Snake:
                    if (0 == round % 2) //even, if it is odd it is the same as regular.
                    {
                        team = m_draftevent.TeamCount - team;
                    }
                    else team = team - 1;
                    break;
                case DraftStyle.Other:      //other defaults to regular
                    team = team - 1;
                    break;
                default:                    //default defaults to regular
                    team = team - 1;
                    break;
            }

            pickindex = (m_draftevent.TeamCount * (round-1)) + team;
            picklookup.PickIndex = pickindex;
            picklookup.PickedID = m_picks[picklookup.PickIndex].PickedID;

            return picklookup;
        }

        public int CurrentRound
        {
            get
            {
                return getRound();
            }
        }

        public int CurrentTeam
        {
            get
            {
                return getTeam();
            }
        }

        /// <param name="PickId">Id of Draftable Object (Player, team, etc.</param>
        public void SelectPick(int pick)
        {
            Pick newpick = new Pick();
            m_pick = (m_pick + 1);
            newpick.PickIndex = m_pick;
            newpick.PickedID = pick;
            m_picks.Add(newpick);
        }

        /// <summary>
        /// Update a particular Pick
        /// </summary>
        /// <remarks>Allows you edit a particular pick, //#ms really should make exceptions here</remarks>
        /// <param name="pick">Pick enum with pick information to change.</param>
        //#ms this really needs help, editing can be dangerous and we need to handle with care.
        //public bool EditPick(int pickindex, int pickid)
        public bool EditPick(Pick pickedit)
        {
            if(pickedit.PickIndex < 0) //checking to see if this is a negative pick index
            {
                return false;
            }
            else if (pickedit.PickIndex > m_picks.Count)  //checking to see if this pickindex hasn't  been used
            {
                return false;
            }
            //#ms if we don't do a check to see if is a valid draft pick we may end up with duplicates draft picks on different teams.
            //else if (m_picks.Contains(pickedit))  //checking if this is an already used draft pick
            //{
            //    return false;
            //}
            else //should be a valid pickindex with a valid pickid
            {
                m_picks[pickedit.PickIndex - 1] = pickedit;
                return true;  //if the pick to edit is valid we update and return true
            }
            //return false;   //if the pick to edit isn't valid then, we return false
        }

        /// <summary>
        /// The current round of the draft.
        /// </summary>
        /// <remarks>Simple Math to return the current round of the draft.</remarks>
        /// <returns>byte</returns>
        private int getRound()
        {
            int round = 0;

            round = ((m_pick -1) / m_draftevent.TeamCount) + 1;

            return round;
        }

        /// <summary>
        /// The current team on the clock
        /// </summary>
        /// <remarks>Might just make this public.</remarks>
        /// <returns>byte</returns>
        private int getTeam()
        {
            int team = 0;

            team = getTeamPick();           //this is the regular setting

            switch(m_draftevent.Style)
            {
                case DraftStyle.Regular:    //Since we already are set to regular, no more needed.
                    break;
                case DraftStyle.Snake:
                    if(0 == getRound() % 2) //even, if it is odd it is the same as regular.
                    {
                        team = m_draftevent.TeamCount - getTeamPick() + 1;
                    }
                    break;
                case DraftStyle.Other:      //other defaults to regular
                    break;
                default:                    //default defaults to regular
                    break;
            }

            return team;
        }

        private int getTeamPick()
        {
            int teampick = 0;

            teampick = m_pick - (getRound() - 1)*m_draftevent.TeamCount;

            return teampick;
        }

        private void Initialize()
        {
            m_pick = 0;
            m_teams.Capacity = m_draftevent.TeamCount;
            m_picks.Capacity = m_draftevent.RoundCount * m_draftevent.TeamCount;
            
            for(int i = 1; i <= m_draftevent.TeamCount; i++)
            {
                m_teams.Add("Team #" + i.ToString());
            }
        }
    }

    public enum DraftStyle
    {
        /// <summary>
        /// Regular Draft
        /// </summary>
        /// <remarks>Each round proceeds in team order.</remarks>
        Regular = 0,
        /// <summary>
        /// Snake Draft
        /// </summary>
        /// <remarks>Odd rounds proceed in team order, even rounds proceed in reverse order.</remarks>
        Snake = 1,
        /// <summary>
        /// Other Draft
        /// </summary>
        /// <remarks>Drafts with other rules yet to be determined.</remarks>
        Other = 10
    }

    public struct Pick
    {
        public int PickIndex { get; set; }
        public int PickedID { get; set; }
        //public int Team { get; set; }
        //public int Round { get; set; }

    }

    public enum DraftType
    {
        Default = 0,
        StarTournament = 5,
    }
}
